 package org.compiere.process;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.logging.Level;

import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.Mhrmemployee;
import org.compiere.model.Mhrmlimitholiday;
import org.compiere.model.Mhrmorder;
import org.compiere.model.Mhrmreserve;
import org.compiere.model.Mhrmreservesectional;
import org.compiere.model.Mhrmsalaryemployee;
import org.compiere.model.Mhrmvacation;
import org.compiere.model.Mhrmvacationline;
import org.compiere.model.X_hrm_order;
import org.compiere.model.X_hrm_salaryemployee;
import org.compiere.model.X_hrm_vacationline;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.eevolution.model.X_HR_Contract;
import org.eevolution.model.X_HR_Employee;
import extend.org.compiere.hrm.AverageCalc;
import extend.org.compiere.hrm.AverageSalary;
import extend.org.compiere.hrm.TaxCompute;
import extend.org.compiere.hrm.TaxVariable;
import extend.org.compiere.hrm.TypePayment;
import extend.org.compiere.utils.Util;

public class GenerateLeaveSalary extends SvrProcess {

	private Timestamp dateFrom;
	private Timestamp dt = null; 
	private Mhrmvacation vpayment = null;
	private Mhrmvacationline hrmvl = null;
	private Mhrmorder vorder = null;
	Calendar date = Calendar.getInstance();
		
	/** Salary */
	Mhrmsalaryemployee salary = null;
	
	/** Tax */
	private TaxVariable taxcomp = null;
	
	/** Average */
	private AverageSalary average = null;	
		
	/**	Employee List	*/
	private Mhrmemployee[] m_orderlines;
	
	/** Holiday limit */
	private Mhrmlimitholiday holiDaylimit = null;
	
	double maid = 0;
	double total = 0;
	double IPN = 0;
	double OPV = 0;
	double CNALOG = 0;
	double COTCH = 0;
	double HOLIDAYS = 2.5;   // 2.5 days set default, in future must be take configuration table
	/** */
	String closeTax = "N";
	
	@Override
	protected void prepare() {
		
		ProcessInfoParameter[] para = getParameter();
		for (int i = 0; i < para.length; i++)
		{
				String name = para[i].getParameterName();
				if (name.equals("CloseTax"))
					closeTax = para[i].getParameter().toString();
				else
					log.log(Level.INFO, "Unknown Parameter: " + name);			
		}	
		
		vpayment = new Mhrmvacation(getCtx(), getRecord_ID(), null); 
	}

	@Override
	protected String doIt() throws Exception {
		
		vorder = new Mhrmorder(getCtx(), vpayment.gethrm_order_ID(), null);
		dateFrom = vorder.getStartDate();
		
		double SUM = .0;
		m_orderlines = vorder.getLinesEmployee();
		for(int i=0; i < m_orderlines.length; i++){
			X_HR_Employee hremp = X_HR_Employee.getHR_Employee(m_orderlines[i].getC_BPartner_ID(), null);
			X_HR_Contract hrcon = X_HR_Contract.getHR_Contract(m_orderlines[i].getC_BPartner_ID(), true);
			if (hremp.getC_BPartner_ID() == 0)
				throw new AdempiereException ("Info about employee was empty, may be employee is dismissed ");
			// record line
			hrmvl = Mhrmvacationline.getVacationline(m_orderlines[i].getC_BPartner_ID(), vorder.getStartDate(), vorder.getEndDate());
			if (hrmvl == null)
				hrmvl = new Mhrmvacationline(getCtx(), 0, get_TrxName());
			hrmvl.sethrm_vacation_ID(vpayment.gethrm_vacation_ID());
			hrmvl.setC_BPartner_ID(hremp.getC_BPartner_ID());
			hrmvl.setHR_Job_ID(hremp.getHR_Job_ID());
			hrmvl.setHR_Department_ID(hremp.getHR_Department_ID());
			hrmvl.setStartDate(vorder.getStartDate());
			hrmvl.setEndDate(vorder.getEndDate());
			hrmvl.sethrm_workleavetype(vorder.gethrm_workleavetype());
							
			//total = 0;
			// get average
			average = AverageCalc.getAvarage(hremp.getC_BPartner_ID(), dateFrom);			
			hrmvl.setDateFrom(average.getSTARTDATE());
			hrmvl.setDateTo(average.getENDDATE());
			total = average.getRESULT();			
			vorder.sethrm_average(new BigDecimal(total));
			hrmvl.sethrm_average(new BigDecimal(total));

			// set material aid
			if (vorder.gethrm_workleavetype().contains(X_hrm_order.HRM_WORKLEAVETYPE_NormVacation) ) {
				salary = Mhrmsalaryemployee.getSalary(hremp.getC_BPartner_ID(), dateFrom);					
				// check employee is work more then one year 
				date.setTime(hrcon.getValidFrom());					
				date.add(Calendar.YEAR, 1);
				date.add(Calendar.DAY_OF_YEAR, -1);
				dt = new Timestamp(date.getTimeInMillis());
				if (dt.after(dateFrom)){
					holiDaylimit = Mhrmlimitholiday.getLimitHoliday(hremp.getC_BPartner_ID(),null);
					int limitdays = holiDaylimit.gethrm_days().intValue();
					int Month = Util.getMonth(holiDaylimit.getStartDate(), dateFrom);
				    if (Month > 12)
				        Month = (Month % 12);	
				    double DAYS = (HOLIDAYS * Month);
				    DAYS = (DAYS % (HOLIDAYS * 12));
					maid = (salary.gethrm_amountsalary().doubleValue()/(HOLIDAYS * 12)) * limitdays;
				}else{
					maid = salary.gethrm_amountsalary().doubleValue() * 2;
				}
				
				/** Calculate material aid tax */			
				/** Generate employee tax */
				taxcomp =  TaxCompute.GetTax(hremp.getC_BPartner_ID(), maid, dateFrom, TypePayment.VACATIONAID);					
				OPV = taxcomp.getOPV();
				IPN = taxcomp.getIPN();
				/** Definition direct (2) or inverse (1 - default) payroll methods */	
				if (X_hrm_salaryemployee.HRM_SALARYTYPE_Direct.equals(salary.gethrm_salarytype())){
					maid = taxcomp.getTOTAL();
				}else{
					maid = taxcomp.getTOTAL() + OPV + IPN;			
				}
				COTCH = taxcomp.getCOTCH();	
				CNALOG = taxcomp.getCNALOG()-COTCH;
				
			}else{
				maid = .0;				
			}
			
			// get work days
			int days = Mhrmvacation.getWorkTime(hremp.getC_BPartner_ID(), vorder.getStartDate(), vorder.getEndDate());
			hrmvl.sethrm_days(days);						
			SUM = (total * days);
			/** Generate employee tax */
			taxcomp =  TaxCompute.GetTax(hremp.getC_BPartner_ID(), SUM, dateFrom, TypePayment.VACATION);
			double vIPN = taxcomp.getIPN();
			double vOPV = taxcomp.getOPV();
			double vCOTCH = taxcomp.getCOTCH();
			double vCNALOG = taxcomp.getCNALOG();
			
			//total = taxcomp.getTOTAL() + taxcomp.getIPN() + taxcomp.getOPV();
			hrmvl.sethrm_materialaid(new BigDecimal(maid));
			hrmvl.sethrm_amountvacation(new BigDecimal(SUM));
			hrmvl.sethrm_IPN(new BigDecimal(vIPN));
			hrmvl.sethrm_OPV(new BigDecimal(vOPV));
			hrmvl.sethrm_total(new BigDecimal(SUM));
			// Set social tax variables
			hrmvl.sethrm_COtch(new BigDecimal(vCOTCH));
			hrmvl.sethrm_CNalog(new BigDecimal(vCNALOG - vCOTCH));		    
			//						
			vorder.saveEx();
			if (closeTax.equals("Y")){
				hrmvl.setProcessed(true);
				vpayment.setProcessed(true);
			}
			hrmvl.saveEx();	
			
			Mhrmreservesectional[] line = Mhrmreservesectional.getMhrmreservesectional(); 
			for(Mhrmreservesectional l: line){
				X_hrm_vacationline vacLine = Mhrmvacationline.getVacationLineAcct(hrmvl.gethrm_vacation_line_ID(), l.gethrm_reservesectional_ID());
				if(vacLine == null)
					vacLine = new X_hrm_vacationline(Env.getCtx(),0,null);
				
				if(l.gethrm_reservesectional_ID() == Mhrmreserve.RESERVE_SECTIONAL_CHARGE){
					vacLine.sethrm_amount(hrmvl.gethrm_total());
					vacLine.sethrm_reservesectional_ID(Mhrmreserve.RESERVE_SECTIONAL_CHARGE);
				}
				else if(l.gethrm_reservesectional_ID() == Mhrmreserve.RESERVE_SECTIONAL_CNALOG){
					vacLine.sethrm_amount(hrmvl.gethrm_CNalog());
					vacLine.sethrm_reservesectional_ID(Mhrmreserve.RESERVE_SECTIONAL_CNALOG);
				}
				else if(l.gethrm_reservesectional_ID() == Mhrmreserve.RESERVE_SECTIONAL_COTCH){
					vacLine.sethrm_amount(hrmvl.gethrm_COtch());
					vacLine.sethrm_reservesectional_ID(Mhrmreserve.RESERVE_SECTIONAL_COTCH);
				}
				vacLine.sethrm_reserve_ID(Mhrmreserve.RESERVE_VACATION);
				vacLine.sethrm_vacation_ID(vpayment.gethrm_vacation_ID());
				vacLine.sethrm_vacation_line_ID(hrmvl.gethrm_vacation_line_ID());
				vacLine.saveEx();
			}
			
		}
	
		return Msg.translate(Env.getCtx(), "Success");
	}

}
